using System;
using System.Collections.Generic;
using UnityEngine;

namespace ZFramework.Runtime
{
    /// <summary>
    /// 框架入口，维护所有模块管理器
    /// </summary>
    public static class FrameworkManagerManager
    {
        /// <summary>
        /// 所有模块管理器的链表
        /// </summary>
        private static LinkedList<FrameworkManagerBase> m_Managers = new LinkedList<FrameworkManagerBase>();

        public static void OnUpdate(float elapseSeconds, float realElapseSeconds)
        {
            //轮询所有管理器
            foreach (FrameworkManagerBase manager in m_Managers)
            {
                manager.OnUpdate(elapseSeconds, realElapseSeconds);
            }
        }

        public static void Shutdown()
        {
            //关闭并清理所有管理器
            for (LinkedListNode<FrameworkManagerBase> current = m_Managers.Last; current != null; current = current.Previous)
            {
                current.Value.Shutdown();
            }

            m_Managers.Clear();
        }

        public static void RegisterManager(FrameworkManagerBase manager)
        {
            if (manager == null)
            {
                Log.Error("FrameworkManagerManager RegisterManager manager is invalid.");
                return;
            }
            
            Type type = manager.GetType();
            var oldManager = GetManager(type);
            if (oldManager != null)
            {
                Log.Error("FrameworkManagerManager RegisterManager 重复类型的mgr=={0}", type.FullName);
                return;
            }

            //根据模块优先级决定它在链表里的位置
            LinkedListNode<FrameworkManagerBase> current = m_Managers.First;
            while (current != null)
            {
                if (manager.Priority > current.Value.Priority)
                {
                    break;
                }

                current = current.Next;
            }

            if (current != null)
            {
                m_Managers.AddBefore(current, manager);
            }
            else
            {
                m_Managers.AddLast(manager);
            }
        }

        public static void ShutdownManager<T>() where T : FrameworkManagerBase
        {
            ShutdownManager(typeof(T));
        }

        public static void ShutdownManager(Type type)
        {
            LinkedListNode<FrameworkManagerBase> current = m_Managers.First;
            while (current != null)
            {
                if (current.Value.GetType() == type)
                {
                    var manager = current.Value;
                    manager.Shutdown();
                    break;
                }

                current = current.Next;
            }
        }

        public static T GetManager<T>() where T : FrameworkManagerBase
        {
            return (T)GetManager(typeof(T));
        }

        public static FrameworkManagerBase GetManager(Type type)
        {
            LinkedListNode<FrameworkManagerBase> current = m_Managers.First;
            while (current != null)
            {
                if (current.Value.GetType() == type)
                {
                    return current.Value;
                }

                current = current.Next;
            }

            return null;
        }
    }
}